﻿using MessageQueues.MSMQ.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Messaging;
using System.Text;
using System.Threading.Tasks;

namespace MessageQueues.MSMQ.Implement
{
    /// <summary>
    /// 消息队列控制器
    /// </summary>
    public partial class MessageQueueHandler : IMessageQueueMethod
    {
        /// <summary>
        /// 启动一个没有超时设定的异步查看操作。直到队列中出现消息时，才完成此操作。
        /// </summary>
        /// <typeparam name="T">获取的消息数据的类型</typeparam>
        /// <param name="action">获取数据后的回调</param>
        public void PeekAsync<T>(Action<T> action) where T : class
        {
            try
            {
                if (!initPeekAsync)
                {
                    queue.PeekCompleted += (sender, e) =>
                    {
                        Message message = queue.EndPeek(e.AsyncResult);
                        T obj = message.Body as T;
                        if (obj != null)
                            action(obj);
                        else
                            throw new InvalidCastException("队列获取的类型与泛型类型不符");
                    };
                    initPeekAsync = true;
                }
                queue.Formatter = new XmlMessageFormatter(new Type[] { typeof(T) });
                queue.BeginPeek();
            }
            catch (Exception)
            {

                throw new Exception("异步读取队列中第一个数据时出现异常");
            }
        }

        /// <summary>
        /// 异步接收队列消息，并删除接收的消息数据
        /// </summary>
        /// <typeparam name="T">返回的数据类型</typeparam>
        /// <param name="action">获取数据后的回调</param>
        public void ReceiveAsync<T>(Action<T> action) where T : class
        {
            try
            {
                if (!initReceiveAsync)
                {
                    queue.ReceiveCompleted += (sender, e) =>
                    {
                        Message message = queue.EndReceive(e.AsyncResult);
                        T obj = message.Body as T;
                        if (obj != null)
                            action(obj);
                        else
                            throw new InvalidCastException("队列获取的类型与泛型类型不符");
                    };
                    initReceiveAsync = true;
                }
                queue.Formatter = new XmlMessageFormatter(new Type[] { typeof(T) });
                queue.BeginReceive();
            }
            catch (Exception)
            {
                throw new Exception("异步获取队列消息时出现异常");
            }
        }

        /// <summary>
        /// 异步循环获取队列消息，调用此方法将一直接收队列数据，直到IsStopReceiveLoop被设置为true
        /// </summary>
        /// <typeparam name="T">返回的数据类型</typeparam>
        /// <param name="action">获取数据后的回调</param>
        public void ReceiveAsyncLoop<T>(Action<T> action) where T : class
        {
            try
            {
                if (!initReceiveAsync)
                {
                    queue.ReceiveCompleted += (sender, e) =>
                    {
                        Message message = queue.EndReceive(e.AsyncResult);
                        T obj = message.Body as T;
                        if (obj != null)
                            action(obj);
                        else
                            throw new InvalidCastException("队列获取的类型与泛型类型不符");

                        // 只要不停止就一直接收
                        if (!IsStopReceiveLoop)
                            queue.BeginReceive();
                    };
                    initReceiveAsync = true;
                }
                queue.Formatter = new XmlMessageFormatter(new Type[] { typeof(T) });
                IsStopReceiveLoop = false;
                queue.BeginReceive();
            }
            catch (Exception)
            {
                throw new Exception("异步循环获取队列消息时出现异常");
            }
        }
    }
}
